from typing import TYPE_CHECKING, Tuple, Optional
import pygame
from const import (
    CELL_SIZE,
    SCREEN_WIDTH,
    SCREEN_HEIGHT,
    PLAYER_PANEL_WIDTH,
    STATUS_PANEL_HEIGHT,
    WHITE, BLACK, RED, BLUE, YELLOW, LIGHT_GRAY, DARK_GRAY,
    GRID_CELL_CLICKED_EVENT,
    Skill
)

if TYPE_CHECKING:
    from model import GridManager, Model
    from .renderer import FontManager



def get_clicked_cell(pos: Tuple[int, int], grid_start_x, grid_start_y, grid_manager: 'GridManager') -> Optional[Tuple[int, int]]:
    """
    将点击位置转换为网格坐标
    """
    x, y = pos
    # 计算网格区域的起始位置
    # grid_start_x = PLAYER_PANEL_WIDTH + (SCREEN_WIDTH - PLAYER_PANEL_WIDTH - grid_manager.grid_size * CELL_SIZE) // 2
    # grid_start_y = STATUS_PANEL_HEIGHT + (SCREEN_HEIGHT - STATUS_PANEL_HEIGHT - grid_manager.grid_size * CELL_SIZE) // 2
    
    # 检查点击是否在网格区域内
    if (x < grid_start_x or x >= grid_start_x + grid_manager.grid_size * CELL_SIZE or
        y < grid_start_y or y >= grid_start_y + grid_manager.grid_size * CELL_SIZE):
        return None
    
    # 计算网格坐标
    grid_x = (x - grid_start_x) // CELL_SIZE
    grid_y = (y - grid_start_y) // CELL_SIZE
    
    return grid_x, grid_y


class GridRenderer:
    def __init__(self, screen, font_mgr: 'FontManager'):
        self.screen = screen
        self.font_mgr = font_mgr
        self.grid_rect = pygame.Rect(0, 0, 0, 0)
        self.hovered_coord: Optional[Tuple[int, int]] = None # 新增：存储悬停的格子坐标

    def handle_mouse_hover(self, mouse_pos: tuple[int, int], grid_manager: 'GridManager') -> None:
        """
        处理鼠标悬停事件，更新悬停的格子坐标

        Args:
            mouse_pos: 鼠标位置坐标
            grid_manager: 网格管理器
        """
        grid_start_x = self.grid_rect.x
        grid_start_y = self.grid_rect.y
        # 更新悬停坐标
        self.hovered_coord = get_clicked_cell(mouse_pos, grid_start_x, grid_start_y, grid_manager)
        

    def handle_click(self, mouse_pos: tuple[int, int], model: 'Model') -> bool:
        """
        处理玩家区域的点击事件

        Args:
            mouse_pos: 鼠标点击位置坐标

        Returns:
            bool: 如果点击在玩家区域内返回True, 否则返回False
        """
        # 判断点击是否在玩家区域内

        grid_start_x = self.grid_rect.x
        grid_start_y = self.grid_rect.y

        grid_coord = get_clicked_cell(mouse_pos, grid_start_x, grid_start_y, model.grid_manager)
        if grid_coord is not None:
            pygame.event.post(pygame.event.Event(GRID_CELL_CLICKED_EVENT, grid_coord=grid_coord))
            return True

        return False

        
    def _draw_cell(self, grid_start_x, grid_start_y, grid_manager: 'GridManager', highlighted_cells: list[Tuple[int, int]], selected_cell: Tuple[int, int]):
        font = self.font_mgr.get_font(36) # 用于绘制棋子
        question_mark_font = self.font_mgr.get_font(48) # 为问号创建一个稍大的字体
        emoji_font = self.font_mgr.get_font(36) # 用于绘制emoji

        for i in range(grid_manager.grid_size + 1):
            pygame.draw.line(self.screen, BLACK,
                            (grid_start_x + i * CELL_SIZE, grid_start_y),
                            (grid_start_x + i * CELL_SIZE, grid_start_y + grid_manager.grid_size * CELL_SIZE))
            pygame.draw.line(self.screen, BLACK,
                            (grid_start_x, grid_start_y + i * CELL_SIZE),
                            (grid_start_x + grid_manager.grid_size * CELL_SIZE, grid_start_y + i * CELL_SIZE))

        for y in range(grid_manager.grid_size):
            for x in range(grid_manager.grid_size):
                cell_x = grid_start_x + x * CELL_SIZE
                cell_y = grid_start_y + y * CELL_SIZE
                cell_rect = pygame.Rect(cell_x + 1, cell_y + 1, CELL_SIZE - 2, CELL_SIZE - 2)

                if (x, y) == selected_cell:
                    pygame.draw.rect(self.screen, DARK_GRAY, cell_rect)
                elif (x, y) in highlighted_cells:
                    pygame.draw.rect(self.screen, YELLOW, cell_rect)

                # 绘制不可放置格子
                if (x, y) in grid_manager.trapped_cells:
                    question_text = question_mark_font.render("×", True, BLACK)
                    question_rect = question_text.get_rect(center=(cell_x + CELL_SIZE // 2, cell_y + CELL_SIZE // 2))
                    self.screen.blit(question_text, question_rect)

                # 绘制中立棋子
                elif hasattr(grid_manager, "neutral_cells") and (x, y) in getattr(grid_manager, "neutral_cells", []):
                    symbol = grid_manager.grid[y][x]
                    emoji_text = emoji_font.render(symbol, True, BLACK)
                    emoji_rect = emoji_text.get_rect(center=(cell_x + CELL_SIZE // 2, cell_y + CELL_SIZE // 2))
                    self.screen.blit(emoji_text, emoji_rect)

                # 绘制玩家棋子
                elif grid_manager.grid[y][x] is not None:
                    symbol = grid_manager.grid[y][x]
                    color = RED if symbol == "A" else BLUE
                    text = font.render(symbol, True, color)
                    text_rect = text.get_rect(center=(cell_x + CELL_SIZE // 2, cell_y + CELL_SIZE // 2))
                    self.screen.blit(text, text_rect)

    def highlight_cell(self, model: 'Model', grid_coord: Optional[Tuple[int, int]]) -> list[Tuple[int, int]]:
        highlighted_cells = []
        selected_pos = model.selected_grid_pos
        selected_skill = model.selected_skill

        grid_manager = model.grid_manager
        
        selected_skill = model.selected_skill

        # 必须有选中的技能且鼠标悬停在格子上才进行高亮计算
        if selected_skill is None or grid_coord is None:
            return highlighted_cells, selected_pos

        hover_x, hover_y = grid_coord
        # print(f"悬停坐标: {grid_coord}, 选中技能: {selected_skill}")
        # print((hover_x, hover_y))

        # 根据不同技能计算高亮区域
        if selected_skill is Skill.CLEAR_COLUMN:
            for y in range(grid_manager.grid_size):
                highlighted_cells.append((hover_x, y))
        elif selected_skill is Skill.CLEAR_ROW:
            for x in range(grid_manager.grid_size):
                highlighted_cells.append((x, hover_y))
        elif selected_skill is Skill.MOVE_PIECE and selected_pos is not None:
            # 如果选中技能是移动棋子，并且已经选择了一个格子
            # 检查当前悬停格子是否为空
            if grid_manager.is_empty_cell(grid_coord):
                # 如果当前悬停格子为空，则高亮当前悬停的格子
                highlighted_cells.append(grid_coord)
        
        elif selected_skill in [Skill.SWAP_PIECES, Skill.EXPAND_GRID]:
            # 如果选中技能是交换棋子或扩展网格
            # 这些技能通常需要选择两个格子，这里先只高亮当前悬停的格子
            # 或者根据游戏逻辑判断是否是第一个选择点
            if grid_manager.grid[hover_y][hover_x] is not None: # 仅当格子上非空时高亮（可调整）
                highlighted_cells.append(grid_coord)
        else:
            # 对于其他技能或默认情况，只高亮当前悬停的格子
            highlighted_cells.append(grid_coord)
            


        return highlighted_cells, selected_pos

    def draw_grid(self, model: 'Model') -> None:
        grid_manager = model.grid_manager

        grid_start_x = PLAYER_PANEL_WIDTH + (SCREEN_WIDTH - PLAYER_PANEL_WIDTH - grid_manager.grid_size * CELL_SIZE) // 2
        grid_start_y = STATUS_PANEL_HEIGHT + (SCREEN_HEIGHT - STATUS_PANEL_HEIGHT - grid_manager.grid_size * CELL_SIZE) // 2

        self.grid_rect = pygame.Rect(grid_start_x, grid_start_y,
                                     grid_manager.grid_size * CELL_SIZE,
                                     grid_manager.grid_size * CELL_SIZE)
        # 先绘制白色背景填充，防止旧内容残留
        pygame.draw.rect(self.screen, WHITE, self.grid_rect)

        # 计算需要高亮的格子
        highlighted_cells, selected_cell = self.highlight_cell(model, self.hovered_coord)

        # 绘制网格线、棋子和高亮
        self._draw_cell(grid_start_x, grid_start_y, grid_manager, highlighted_cells, selected_cell) # 传递高亮列表